/*
 * Copyright 2008 Lamen Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at 
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and 
 * limitations under the License.
*/

package org.lamen;

import java.io.File;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.TreeSet;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

/**
 * Created to ease the test process, this test suite runs all Lamen Junit test cases.
 * To add a test to Lamen test suite, test classes should extend {@linkplain TestCase}.
 * 
 * @author danielfireman
 * 
 * @date Jan 15, 2009
 */
public class LamenTestSuite {

  @SuppressWarnings("unchecked")
  public static Test suite() {
    TestSuite suite = new TestSuite("Test for org.lamen");
    try {
      List<Class> classes = findTestClasses(new File("classes"));
      for (Class test : classes) {
        suite.addTestSuite(test);
      }
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    }
    return suite;
  }

  /**
   * Get all test classes in some directory and its subdirectories. By test classes we mean classes which its name ends with "Test.class".
   * @param root The search origin
   * @return A list containing all test classes found
   * @throws ClassNotFoundException If the file which its name ends with "Test.class" is not a Java class. For more info check {@link Class#forName(String)}.
   */
  @SuppressWarnings("unchecked")
  private static List<Class> findTestClasses(File root) throws ClassNotFoundException {
    List<Class> classes = new LinkedList<Class>();
    if (!root.isDirectory() || root.isHidden() ){
      return classes;
    }
    
    TreeSet<File> toProcess = new TreeSet<File>(Arrays.asList(root.listFiles()));
    while (!toProcess.isEmpty()) {
      File file = toProcess.first();
      if (file.isDirectory() && !file.isHidden()){
        toProcess.addAll(Arrays.asList(file.listFiles()));
      } else if (file.getName().endsWith("Test.class")){
        String className = file.getPath().substring(root.getName().length()+1).replaceAll("/", "\\.");
        classes.add(Class.forName(className.substring(0, className.length() - 6)));
      }
      toProcess.remove(file);
    }
    
    return classes;
  }
}
